<?php
/***
 * Candy 支付类库文件
 *
 * $Author: 刘森 (fingerboy@qq.com) $
 * $Date: 2020-05-24 00:28:25 $
 */
 
declare(strict_types=1);
namespace Candy\Extend;
use \Candy\Extend\Network\{Client,Http};
use \Candy\Core\Tpl;
defined('CANDY') OR die('You Are A Bad Guy. o_O???');

final Class Pay {
	/**
	 * 支付宝支付接口
	 */
	public static function aliPay(array $data = []): string
	{
		if(is_null(G('payment'))) Tpl::report(__FILE__,__LINE__,'Error#M.7');
		$payment = G('payment');
		
		$postData = [
				'service'=>'create_direct_pay_by_user',
				'partner'=>$payment['alipid'],
				'_input_charset'=>'utf-8',
				'notify_url'=>$payment['notifyurl'],
				'return_url'=>$payment['returnurl'],
				'out_trade_no'=>$data['id'],
				'subject'=>$data['title'],	
				'payment_type'=>'1',
				'total_fee'=>intval($data['total'])/100,
				'seller_id'=>$payment['alipid'],
				'it_b_pay'=>'1h',
			];
		if(isset($data['qr'])){
			if(isset($data['qr']['width'])){
				$QRData = ['qr_pay_mode'=>'4','qrcode_width'=>$data['qr']['width']];
				$postData = array_merge($postData,$QRData);
			}
			else{
				$QRData = ['qr_pay_mode'=>'3'];
				$postData = array_merge($postData,$QRData);
			}
		}
		ksort($postData);
		$sortString = null;
		foreach ($postData as $key => $val){
			$sortString .= $key .'='. $val .'&';
		}
		$sortString = substr($sortString, 0, -1);
		$sign = md5($sortString . $payment['alikey']);
		$sortString.='&sign='.$sign.'&sign_type=MD5';
		return 'https://mapi.alipay.com/gateway.do?'.$sortString;
	}
	
	/**
	 * 微信支付接口
	 */
	public static function wxPay(array $data = []): string
	{
		if(is_null(G('payment'))) Tpl::report(__FILE__,__LINE__,'Error#M.7');
		$payment = G('payment');
		
		if(empty($data['ip'])){
			$ip = Client::getClientIp();
 		}
		
		if(empty($data['mode'])){
			$mode = 'NATIVE';
 		}
		
		$string = null;
		$word = '0123456789qwertyuiopasdfghjklzxcvbnm';
		for($n=1;$n<=31;$n++){
			$random = mt_rand(0,34);
			$string .= $word[$random];
		}
		$expireTime = date('YmdHis', gmTime() + 3600);
		$postData = [
				'appid'=>$payment['wxappid'],
				'mch_id'=>$payment['wxmchid'],
				'nonce_str'=>$string,
				'body'=>$data['title'],
				'out_trade_no'=>$data['id'],
				'total_fee'=>$data['total'],
				'spbill_create_ip'=>$ip,
				'time_expire'=>$expireTime,
				'notify_url'=>$payment['notifyurl'],
				'trade_type'=>$mode,
			];
		if($mode == 'JSAPI'){
			$postData['openid'] = $data['openid'];
		}
		if($mode == 'MWEB'){
			$postData['scene_info'] = json_encode($payment['wxsceneinfo']);
		}
		ksort($postData);
		$sortString = null;
		foreach ($postData as $key => $val){
			$sortString .= $key .'='. $val .'&';
		}
		$sign = md5($sortString .'key='. $payment['wxkey']);
		
		$pay = '<?xml version=\'1.0\'?>'."\r\n".
		'<xml>'."\r\n".
		'<appid>'.$payment['wxappid'].'</appid>'."\r\n".
		'<mch_id>'.$payment['wxmchid'].'</mch_id>'."\r\n".
		'<nonce_str>'.$string.'</nonce_str>'."\r\n".
		'<body>'.$data['title'].'</body>'."\r\n".
		'<out_trade_no>'.$data['id'].'</out_trade_no>'."\r\n".
		'<total_fee>'.$data['total'].'</total_fee>'."\r\n".
		'<spbill_create_ip>'.$ip.'</spbill_create_ip>'."\r\n".
		'<time_expire>'.$expireTime.'</time_expire>'."\r\n".
		'<notify_url>'.$payment['notifyurl'].'</notify_url>'."\r\n".
		'<trade_type>'.$mode.'</trade_type>'."\r\n";
		if($mode == 'JSAPI'){
			$pay .= '<openid>'.$data['openid'].'</openid>'."\r\n";
		}
		if($mode == 'MWEB'){
			$pay .= '<scene_info>'.json_encode($payment['wxsceneinfo']).'</scene_info>'."\r\n";
		}
		$pay .= '<sign>'.$sign.'</sign>'."\r\n".
		'</xml>
		';

		$info = Http::post('https://api.mch.weixin.qq.com/pay/unifiedorder', $pay, [
			'header'=>'Content-Type: text/xml; charset=UTF-8',
			'encode'=> true,
			'timeout'=> 5]);
		
		xml_parse_into_struct(xml_parser_create(), $info, $returnInfo);
		$return = false;
		if(empty($returnInfo)){
			Tpl::report(__FILE__,__LINE__,'Error#M.7.0');
		}
		$result = true;
		foreach($returnInfo as $val){
			if($val['tag'] == 'RETURN_CODE' && $val['value'] != 'SUCCESS'){
				$result=false;
			}
			if(!$result && $val['tag'] == 'RETURN_MSG'){
				Tpl::report(__FILE__,__LINE__,'Error#M.7.1 @ '.$val['value']);
			}
			if($val['tag'] == 'PREPAY_ID' && $mode == 'JSAPI'){
				$result=$val['value'];
			}
			if($val['tag'] == 'CODE_URL' && $mode == 'NATIVE'){
				$result=$val['value'];
			}
			if($val['tag'] == 'MWEB_URL' && $mode == 'MWEB'){
				$result = $val['value'];
			}
		}
		return $result;
	}
	
	/**
	 * 支付宝支付验签
	 */
	public static function aliPayVerify(array $data = []): bool
	{
		$postData = I('post');
		if(empty($postData)){
			return false;
		}
		if($postData['trade_status'] != 'TRADE_SUCCESS'){
			return false;
		}
		ksort($postData);
		$willCheck = null;
		foreach($postData as $key => $val){
			if($key != 'sign' && $key != 'sign_type' && !empty($val)){
				$willCheck .= $key .'=';
				$willCheck .= $val .'&';
			}
		}
		$willCheck = substr($willCheck, 0, -1);
		$sign = md5($willCheck . $payment['alikey']);
		if($sign != $postData['sign']){
			return false;
		}
		
		if(is_null(G('payment'))) Tpl::report(__FILE__,__LINE__,'Error#M.7');
		$payment = G('payment');
		$notifyResult = Http::get('https://mapi.alipay.com/gateway.do?service=notify_verify&partner='. $payment['alipid'] .'&notify_id='.$postData['notify_id']);
		if(strtoupper($notifyResult) == 'true'){
			return true;
		}
		else{
			return false;
		}
	}
	
	/**
	 * 微信支付验签
	 */
	public static function wxPayVerify(string $string = ''): bool
	{
		$xmlArray = json_decode(json_encode(simplexml_load_string($string,'SimpleXMLElement',LIBXML_NOCDATA)),TRUE);
		if(empty($xmlArray)){
			return false;
		}
		ksort($xmlArray);
		$willCheck = null;
		foreach($xmlArray as $key => $val){
			if($key != 'sign' && !empty($val) && !is_array($val)){
				$willCheck .= $key .'='. $val.'&';
			}
		}
		if(is_null(G('payment'))) Tpl::report(__FILE__,__LINE__,'Error#M.7');
		$payment = G('payment');
		$sign=strtoupper(md5($willCheck .'key='. $payment['wxkey']));
		if($sign == $xmlArray['sign']){
			return true;
		}
		else{
			return false;
		}
	}
}
